import 'dart:async';

import 'package:cave_flutter/common/chat_manager.dart';
import 'package:cave_flutter/config/whl_base_controller.dart';
import 'package:cave_flutter/model/user_model.dart';
import 'package:cave_flutter/utils/extension/string_extension.dart';
import 'package:dio/dio.dart' as myDio;
import 'package:easy_refresh/easy_refresh.dart';
import 'package:flutter/cupertino.dart';
import 'package:get/get.dart';
import 'package:http_parser/http_parser.dart';
import 'package:nim_core/nim_core.dart';

import '../../../model/image_model.dart';
import '../../../network/whl_api.dart';
import '../../../routes/whl_app_pages.dart';
import '../../../utils/event_bus_utils.dart';
import '../../../utils/imageUtils.dart';

class WhlChatRoomLogic extends WhlBaseController {
  // late RCIMIWConversation conversation;
  List messageList = [];
  EasyRefreshController refreshController = EasyRefreshController(
      controlFinishRefresh: true, controlFinishLoad: true);
  ScrollController scrollController = ScrollController();
  bool isShowKeyBoard = false;
  String showName = '';
  // String toAccountId = '17057639733480000000022';
  String toAccountId = '';

  int pageSize = 20;
  int timeTag = 0;

  // 'session': session,
  // NIMSessionType.team
  NIMSessionType sessionType = NIMSessionType.p2p;

  MessageService messageService = NimCore.instance.messageService;
  ChatManager manager = ChatManager.getInstance();
  StreamSubscription? sendMsgSubscription;

  StreamSubscription? reviceMsgSubscription;
  StreamSubscription? messageReceiptSubscription;

  NIMMessage? oldMessage;

  /// 正在播放的语音消息
  NIMMessage? playingModel;

  UserModel? userModel;

  @override
  void onClose() {
    super.onClose();
    scrollController.dispose();
    sendMsgSubscription?.cancel();
    reviceMsgSubscription?.cancel();
    messageReceiptSubscription?.cancel();
    messageService.setChattingAccount(
        sessionId: "none", sessionType: sessionType);

    /// 清除未读消息数
  }

  @override
  void onInit() {
    super.onInit();
    var a = Get.arguments;
    if (a != null) {
      if (a['showName'] != null) {
        showName = a['showName'];
      }
      if (a['toAccountId'] != null) {
        toAccountId = a['toAccountId'];
      }

      if (a["userModel"] != null) {
        userModel = a["userModel"];
      }
    }
    if (userModel == null) {
      getAllUserInfo();
    }
    messageService.setChattingAccount(
        sessionId: toAccountId, sessionType: sessionType);
    onGetMessageList();
    addMessageListener();
  }

  addMessageListener() {
    sendMsgSubscription =
        messageService.onMessageStatus.listen((NIMMessage message) {
      messageList.forEach((element) {
        NIMMessage oldMessage = element;
        if (oldMessage.uuid == message.uuid) {
          oldMessage.status = message.status;
        }
      });
      update();
      // 1、根据sessionId判断是否是自己的消息
      // 2、更改内存中消息的状态
      // 3、刷新界面
    });

    reviceMsgSubscription =
        EventBusUtils.getInstance().eventBus.on<NIMMessage>().listen((event) {
      // All events are of type UserLoggedInEvent (or subtypes of it).
      if (event.sessionId == toAccountId) {
        messageList.insert(0, event);
        messageService.sendMessageReceipt(
            sessionId: toAccountId, message: event);
        update();
        onScrollToBottom();
        // conversationListLogic.update();
      }
    });

    messageReceiptSubscription =
        messageService.onMessageReceipt.listen((event) {
      for (NIMMessageReceipt element in event) {
        if (element.sessionId == toAccountId) {
          for (NIMMessage msg in messageList) {
            msg.isRemoteRead = true;
          }
        }
      }
      update();
    });
  }

  getAllUserInfo() {
    List allIds = [toAccountId];
    WhlApi.batchReplaceUserInfo.post(allIds).then((value) {
      if (value.isSuccess()) {
        List data = value.data ?? [];
        List<UserModel> models =
            data.map((e) => UserModel.fromJson(e)).toList();
        if (models.first != null) {
          userModel = models.first;
        }
        update();
      }
    });
  }

  createAndSendMessageModelWithData(
      {var data,
      String? fileName,
      String? suffix,
      Size? size,
      String? mimeType,
      int? time,
      int? dataLength,
      NIMMessageType type = NIMMessageType.text}) async {
    NIMMessage? message;
    size ??= Size(0, 0);
    if (type == NIMMessageType.text) {
      NIMResult<NIMMessage> result = await MessageBuilder.createTextMessage(
          sessionId: toAccountId, sessionType: sessionType, text: data);
      message = result.data;
      sendMsgToService(result, data);
    } else if (type == NIMMessageType.image) {
      NIMResult<NIMMessage> result = await MessageBuilder.createImageMessage(
        sessionId: toAccountId,
        sessionType: sessionType,
        filePath: data,
        fileSize: dataLength ?? 0,
        displayName: fileName,
        // base64: base64,
        // nosScene: NIMNosScene.defaultIm
      );
      message = result.data;
      print("mimeType === $mimeType");
      uploadFile(result, mimeType: mimeType, suffix: suffix);
    } else if (type == NIMMessageType.audio) {
      NIMResult<NIMMessage> result = await MessageBuilder.createAudioMessage(
        sessionId: toAccountId,
        sessionType: sessionType,
        filePath: data,
        fileSize: dataLength ?? 0,
        // base64: base64,
        duration: time ?? 0,
        displayName: fileName,
        // nosScene: NIMNosScene.defaultIm
      );
      message = result.data;
      uploadFile(result, mimeType: mimeType, suffix: suffix);
    } else if (type == NIMMessageType.video) {
      NIMResult<NIMMessage> result = await MessageBuilder.createVideoMessage(
        sessionId: toAccountId,
        sessionType: sessionType,
        filePath: data,
        fileSize: dataLength ?? 0,
        duration: time ?? 0,
        displayName: fileName ?? "",
        width: int.parse(size.width.toString()),
        height: int.parse(size.height.toString()),
        // nosScene: NIMNosScene.defaultIm
      );
      message = result.data;
      uploadFile(result, mimeType: mimeType, suffix: suffix);
    }

    messageList.insert(0, message);
    // manager.sendMessageToIM(message: message!, resend: false);
    onScrollToBottom();
    update();
  }

  Future<void> uploadFile(
    NIMResult<NIMMessage> result, {
    String? mimeType,
    String? suffix,
  }) async {
    NIMMessage? message = result.data;
    bool isImage = message?.messageType == NIMMessageType.image;
    Map<String, dynamic> dic = result.data?.messageAttachment?.toMap() ?? {};
    print("start upload ----");
    print(dic);
    String filePath = dic["path"] ?? "";
    String fileName = dic["name"] ?? "";
    print("filePath ---- $filePath");

    Map<String, dynamic> params = {
      "path": isImage ? "image" : "file",
      "file": isImage
          ? myDio.MultipartFile.fromBytes(
              await compressImageToCustomSize(filePath),
              filename: fileName,
              contentType: (mimeType ?? "").isNotEmpty
                  ? MediaType.parse(mimeType!)
                  : suffix?.getMediaType())
          : await myDio.MultipartFile.fromFile(filePath,
              filename: fileName,
              contentType: (mimeType ?? "").isNotEmpty
                  ? MediaType.parse(mimeType!)
                  : suffix?.getMediaType()),
    };
    ResponseData response = await WhlApi.uploadFile.post(params, isJson: false);
    if (response.isSuccess()) {
      ImageModel model = ImageModel.fromJson(response.data);
      sendMsgToService(result, model.imageUrl ?? "");
    }
    update();
  }

  sendMsgToService(NIMResult<NIMMessage> result, String context) {
    NIMMessage? message = result.data;
    if (message == null) {
      return;
    }
    int messageType = 0;
    if (message.messageType == NIMMessageType.text) {
      messageType = 0;
    } else if (message.messageType == NIMMessageType.image) {
      messageType = 1;
    } else if (message.messageType == NIMMessageType.audio) {
      messageType = 2;
    } else if (message.messageType == NIMMessageType.video) {
      messageType = 3;
    }
    //消息类型 0：文本消息 1：图片消息 2：语音消息 3：视频消息 4：地理位置消息 6：文件消息
    Map<String, dynamic> param = {
      "message": context,
      "toAccountId": userModel?.accountId,
      "messageType": messageType,
    };

    WhlApi.sendChatSingleMessage.post(param, withLoading: false).then((value) {
      if (value.isSuccess()) {
        manager.sendMessageToIM(message: message, resend: false);
      }
    });
  }

  onGetMessageList({bool isRefresh = false}) async {
    if (oldMessage == null || isRefresh) {
      NIMResult<NIMMessage> result = await MessageBuilder.createEmptyMessage(
          sessionId: toAccountId,
          sessionType: NIMSessionType.p2p,
          timestamp: DateTime.now().millisecondsSinceEpoch);
      oldMessage = result.data;
    }

    NIMResult<List<NIMMessage>> oldResult = await messageService
        .queryMessageListEx(oldMessage!, QueryDirection.QUERY_OLD, pageSize);
    List<NIMMessage> resultList = (oldResult.data ?? []).reversed.toList();
    messageList.addAll(resultList);
    if (resultList.length < pageSize) {
      refreshController.finishLoad(IndicatorResult.noMore);
    }
    if (resultList.isNotEmpty) {
      oldMessage = resultList.last;
      messageService.sendMessageReceipt(
          sessionId: toAccountId, message: resultList.first);
    }
    update();
  }

  onScrollToBottom({bool isSelf = false}) async {
    if (scrollController.position.pixels ==
        scrollController.position.minScrollExtent) {
      // isAutoScroll = false;
      return;
    }
    // isAutoScroll = true;
    scrollController
        ?.animateTo(scrollController.position.minScrollExtent,
            duration: const Duration(milliseconds: 200), curve: Curves.ease)
        .then((value) {
      if (!isSelf) {
        // isAutoScroll = false;
      }
    });
  }

  formatMessageDatas() {
    List resMessageList = messageList.reversed.toList();
    for (NIMMessage element in resMessageList) {
      bool needShowTime = checkNeedShowTime(element);
      Map<String, dynamic> dic = element.localExtension ?? {};
      dic["needShowTime"] = needShowTime;
      element.localExtension = dic;
    }
    timeTag = 0;
  }

  bool checkNeedShowTime(NIMMessage message) {
    int msgTime = message.timestamp ~/ 1000;
    int interval = (timeTag - msgTime);
    if (timeTag == 0 || interval > 60 * 2 || interval < -60 * 2) {
      // print(msgTime);
      // print("show $msgTime ---- $interval--- $timeTag");
      timeTag = msgTime;
      return true;
    }
    // print("hide $msgTime ---- $interval--- $timeTag");
    return false;
  }

  doClickMore() async {
    Get.toNamed(Routes.chatSetting, arguments: {
      "toAccountId": toAccountId,
      "sessionType": sessionType,
      "userModel": userModel
    });
  }
}
